\documentclass[a4paper,12pt,russian]{report}
\usepackage[T2A]{fontenc}
\usepackage[utf8]{inputenc} % любая желаемая кодировка
\usepackage[pdftex,unicode]{hyperref}
\usepackage{array}
\usepackage[russian]{babel} 
\usepackage{cmap}
\usepackage{indentfirst} % включить отступ у первого абзаца
\usepackage[top=10mm,bottom=15mm,left=15mm,right=15mm,includehead,head=12pt,headsep=0cm,includefoot,foot=10pt]{geometry}
\usepackage{graphicx}
\usepackage[usenames]{color}
\usepackage{colortbl}
\usepackage{listings}
\lstset{
  language=C, extendedchars=\true
}
\graphicspath{{images/}}

\linespread{1.5} % полуторный интервал

\title{Пособие по курсу: \\{\bfПрограммно-алгоритмическое обеспечение вычислительных средств АИУС}}
\author{Кондрашов К. С.}
\date{2012}

\begin{document} % начало документа
\def\chaptername{Модуль}

\maketitle % Титульная страница
\tableofcontents

\chapter{Понятие о встраиваемых программируемых системах и системах реального времени}
\section{Введение в задачи управления в АИУС}

Данный курс посвящен разработкe программных средств и алгоритмов, имеющих специфическое назначение. Из названия понятно, что они функционируют на базе вычислительных средств в автономных информационных и управляющих системах (АИУС). Каковы же особенности программ и алгоритмов в данном случае? Курс информатики в школе и вузе позволяет составить общее представление об архитектуре компьютеров, системных и прикладных программах, языках программирования и типичных задачах, решаемых при помощи компьютеров. Предполагается, что студенты, приступающие к изучению данного курса, знакомы с основами программирования и ключевыми особенностями архитектуры вычислительных средств. На базе этих знаний мы рассмотрим написание программ для компьютеров специального назначения. Архитектура их, впрочем, может быть весьма похожа на персональные компьютеры, однако применение существенно отличается. Данный раздел последовательно вводит в <<курс дела>>: знакомит с задачами, методами их решения и требованиями, которые предъявляются к программным средствам и алгоритмам при решении данных задач.

\subsection{Понятие системы и ее свойства}
В данном курсе мы будем иметь дело с техническими{\it системами} (к ним относятся АИУС), которыми предполагается управлять программными средствами. В качестве примера общеизвестных технических систем можно привести:
\begin{itemize}
\item космический корабль,
\item производственный цех,
\item автомобиль,
\item атомная электростанция.
\end{itemize}

Данный список можно продолжать до бесконечности. В каждом из рассмотренных случаев можно выделить общие черты, которые позволяют говорить о том, что мы действительно имеем дело с системой:
\begin{itemize}
\item{\bfЦелостность}. Это основополагающее свойство системы. Оно подразумевает невозможность функционирования того, что мы понимаем под системой в данном конкретном случае, без одной из ее составных частей. Скажем, автомобилем достаточно проблематично управлять без рулевого колеса. Причем само по себе рулевое колесо также уже не может выполнять функции, для которой предназначалось, если оно просто лежит в багажнике.
\item{\bfДелимость}. Каждая система может быть {\itдекомпозирована} на отдельные элементы (по крайней мере, в уме). В свою очередь, элементы системы могут представлять собой также системы (или подсистемы), выражая тем самым ее {\itиерархичность}.
\item{\bfНаличие устойчивых связей}. Данное свойство соотносится с целостностью системы, поскольку именно устойчивые связи позволяют ее элементам взаимодействовать друг с другом согласованно, определяя свойства системы в целом.
\item{\bfЭмерджерность}. Это свойство означает, что отдельные элементы не обладают свойствами системы в целом.
\end{itemize}

Резюмирую, можно сказать, что {\itсистема представляет собой совокупность взаимодействующих между собой элементов, которые образуют ее свойства. Отсутствие того или иного элемента приводит к изменению свойств системы. По отдельности элементы системы не обладают свойствами системы в целом}.

\subsection{Информационно-управляющие системы}
В наши дни технические системы, помимо чисто механических частей, зачастую связаны с обработкой и использованием {\itинформации} в той или иной форме. С точки зрения технической системы информация включает в себя сведения, необходимые для ее функционирования. Для управления автомобилем, в частности, бортовой компьютер должен учитывать следующие факторы:
\begin{itemize}
\item температура окружающей среды,
\item скорость движения,
\item качество дорожного покрытия,
\item местоположение препятствий и т. д.
\end{itemize}

Побочные сведения, которые никак не могут повлиять на работу системы, информационной ценности для нее не несут.

В дальнейшем мы будем говорить о системах, задача которых заключается в том, чтобы в течение некоторого промежутка времени изменять физические величины в том или ином управляемом процессе на основе информации, которая в них поступает. АИУС являются именно такими системами. Кроме того, они предполагают функционирование автономно, то есть в условиях, когда человек не может вмешаться в их работу (работа технического средства без участия человека называется {\itавтоматической}. В автономных системах такое участие к тому же невозможно). Ясно, что к данным управляющим системам предъявляются особые требования, в отличие от, скажем, полуавтоматических систем (например, системы управления станком или билетопечатающего автомата).

Важнейшим классом управляющих систем являются автоматические системы с замкнутым контуром (см Рис.~\ref{ris:loop_system}). Управляющее устройство формирует воздействие для объекта управления, при этом он изменяет свое состояние. При этом управляющее устройство может наблюдать за состоянием объекта управления и корректировать управляющее воздействие в зависимости от решаемой задачи.

\begin{figure}[h]
\center{\includegraphics[width=0.75\linewidth]{loop_system}}
\caption{Система с замкнутым управляющим контуром.}
\label{ris:loop_system}
\end{figure}

\subsection{Устойчивость и точность управляющих систем}
Для описания качества работы управляющих систем в теории управления вводятся понятия {\itустойчивости} и {\itточности}.

Основные идеи, касающиеся понятия устойчивости, таковы. Система считается устойчивой, если после воздействия, имеющего конечную продолжительность, она возвращается в исходное состояние. Устойчивым является, скажем, шарик, находящийся в нижней точки полусферической чаши. Приментельно к информационным управляющим системам понятие устойчивости предполагает устойчивость объекта управления. При этом в зависимости от применяемого в устройстве управления алгоритма, система с неустойчивым объектом управления может стать устойчивой, и наоборот. Кроме того, может существовать несколько устойчивых состояний. Важно также отметить, что системы управления редко решают задачу поддержания конкретно состояния равновесия, а должны обеспечивать некоторый процесс во времени (скажем, движение антенны при сопровождении объекта локации).

Существует обширная математическая теория устойчивости, разработанная А. И. Ляпуновым. В ней используется понятие {\itсостояния} системы $X$. Множество всех возможных состояний называется {\itфазовым пространством}. Состояние системы описывается вектором некоторых параметров системы:

\begin{equation}
\label{eq:state}
X = \{x_1, x_2, ..., x_n\}
\end{equation}

Также задается множество моментов времени $T$, в которые может изменяться состояние системы. Вектор состояний системы (\ref{eq:state}), таким образом, с течением времени прочерчивает некоторую траекторию в фазовом пространстве, осуществляя {\itдвижение} системы. Классическая теория устойчивости рассматривает не устойчивость системы как таковой, а устойчивость ее {\itневозмущенного движения}, то есть такой фазовой траектории, которая соответствует отсутствию к моменту времени $t=0$ действия внешних сил. Другие движения называются {\itвозмущенными}.

На Рис.~\ref{ris:stable} предполагается, что вектор состояния имеет размерность 2. Невозмущенное движение происходит из начального состояния $A$. Переведя до момента времени $t=0$ систему в состояние $A'$ мы получили движение, которое с течением времени не слишком сильно отличается от невозмущенного. Напротив, движение из состояния $A''$, очевидно, отличается от него сильно. Невозмущенное движение (из состояния $A$) называется устойчивым, если отклонение возмущенного движения $dX_1(t), dX_2(t)$ остается малым, когда возмущение $dX_1(0), dX_2(0)$ не слишком велико. 

{\scriptsize
Строгая формулировка такова: невозмущенное движение является устойчивым, если для любых сколь угодно малых ${\epsilon}_i$ можно найти такие ${\eta}_i, {\Delta}X_i(0) < {\eta}_i({\epsilon}_i)$, что отклонения от невозмущенного движения ${\Delta}X_i(t)$ удовлетворяли условиям $\langle{\Delta}X_i(t)\rangle < {\epsilon}_i$. Данное определение называется {\itустойчивостью по Ляпунову}.}

На бытовом уровне понятно, что если, скажем, объектом управления является антенна, то она управляется устойчиво, если в процессе движения не совершает рывков, неконтролируемых колебаний и т. д.

\begin{figure}[h]
\center{\includegraphics[width=0.75\linewidth]{stable}}
\caption{Иллюстрация понятия устойчивости.}
\label{ris:stable}
\end{figure}

Помимо устойчивости важную роль играет также точность управления. При этом говорят об ошибке управления, равной разности между требуемой $g(t)$ и действительной $y(t)$ управляемой величиной:
\begin{equation}
e(t) = g(t) - y(t)
\end{equation}

Для оценки точности данную ошибку можно измерять в различных стандартных режимах работы системы. К ним относятся:
\begin{itemize}
\item неподвижное состояние ({\itстатическая ошибка}),
\item движение с постоянной скоростью -- в этом режиме помиом статической присутствует также {\itскоростная ошибка},
\item движение с постоянным ускорением,
\item синусоидальное движение.
\end{itemize}

Возвращаясь к примеру с антенной, можно заметить, что измерение данных видов ошибки является частью стандартных проверок системы управления и привода антенны на этапе ввода ее в эксплуатацию.

\subsection{Алгоритмы и программы управления в информационных системах}
На этапе становления теории управления существовало большое количество управляющих систем, функционирование которых было основано на использовании всевозможных механизмо, например, регулятор давления пара в котле паровоза. Использование электрического тока позволило значительно усложнить управляющие системы. Электрические двигатели и магнитные реле позволяли при этом сопрягать электрическую часть системы с механической. Непосредственная величина напряжения или тока использовалась в системах управления для формирования управляющих воздействий, измерения параметров объекта управления. Преобразование этих величин позволяло осуществлять всевозможные алгоритмы управления, скажем, принимать решение о наличии или отсутствии препятствия по величине отраженного сигнала и изменении направления движения и т. д.

С появлением активных полупроводниковых приборов стало возможным значительно усложить алгоритмы управления. Малогабаритные транзисторы, а затем и интегральные схемы можно было поместить в боеголовку ракеты, где с их помощью осуществлялась работа алгоритма подрыва ракеты при приближении к цели, в космический аппарат -- везде, где играют важную роль массо-габаритные характеристики. С годами такие полупроводники становились все меньше, потребляли все меньше энергии, открывая новые перспективы их использования в различных областях.

В наши дни широкое распространение получили программные системы управления. В отличие от схемотехнических решений, они обладат несравнимо большей гибкостью, при этом могут применяться в широком спектре случаев, будучи реализованы в виде программы для серийно выпускаемых вычислительных средств. Кроме того, вносить правки в такие системы значительно проще -- это не требует физического вмешательства в конфигурацию устройства управления.

Типичными задачами, решаемыми в АИУС программными средствами, являются:
\begin{itemize}
\item {\itФильтрация и экстраполяция данных.} Эти задачи подразумевают обработку последовательно поступающих на вход системы управления отметок и <<сглаживание>> процесса, который они реализуют. В курсе будет приведен ряд примеров алгоритмов и программных решений данной задачи в простейших случаях.
\item {\itПринятие управляющих решений.} Алгоритмы принятия управляющих решений подразумевают анализ информации, которая для этого необходима, и изменение состояния объекта управления. Примеры таких алгоритмов уже приводились выше.
\item {\itОрганизация обменов и системообразующая функция.} Зачастую программные средства удобны для соединения отдельных частей системы управления в целом (помимо программных средств управления). Это удобство обусловлено, главным образом, гибкостью программных решений.
\end{itemize}

При написании программ, осуществляющих управление техническими средствами, необходимо придерживаться определенных правил, ведь ошибки функционирования устройств управления может привести к аварии в объекте управления, что имеет непоправимые последствия. Прежде всего, это касается обработки исключительных ситуаций. Известны случаи, когда программные ошибки в экстремальных случаях приводили к краху программы. Источником таких ошибок могут являться:
\begin{itemize}
\item арифметически некорректные вычисления: деление на 0, извлечение арифметического корня из отрицательных чисел и т. д.,
\item обращение к некорректному месту в памяти (в частности при выходе за границы массива),
\item формирование физически нереализуемых управляющих воздействий для объекта управления,
\item и прочие.
\end{itemize}

Далее в курсе будут подробно рассмотрены программные ошибки и методы их поиска и устранения.

Помимо исключительных ситуаций, следует понимать, что программы для управления техническими средствами функционируют в реальном масштабе времени. Это подразумевает завершение тех или иных операций за определенные промежутки времени, которые заранее известны. Программа не может <<зациклиться>> или рассчитывать управляющее воздействие слишком долго -- это также приведет к необратимым последствиям. Вопросы работы программ в реальном времени будут также подробно рассмотрены в курсе.

\paragraph{Пример мобильного робота}
\label {ex:simple_robot}
Для примера рассмотрим упрощенную работу некоторого робота, который движется по комнате. В его распоряжении -- ИК-датчик, позволяющий определить, что перед ним преграда. Робот запоминает положение преград, и минует столкновений. Упрощенный алгоритм его работы показан на Рис.~\ref{ris:simple_robot}.

\begin{figure}[h]
\center{\includegraphics[width=0.75\linewidth]{simple_robot}}
\caption{Упрощенный алгоритм работы мобильного робота.}
\label{ris:simple_robot}
\end{figure}

Программная реализация управления таким роботом должна содержать следующие сущности:
\begin{itemize}
\item карту взаимного расположения преград,
\item блок обработки данных с датчика,
\item блок принятия решения о направлении движения,
\item блок выработки управления двигателю и поворотному приводу.
\end{itemize}

При этом уже в такой простой задаче ясно видно, какие сложности могут возникнуть при реализации программного обеспечения и синтезе алгоритма управления. Как быстро нужно обработать данные с датчика, чтобы избежать столкновения? С какой скоростью должен двигаться при этом робот? Понятно, что решение о выработке направления движения должно выполняться оперативно и использовать имеющиеся данные о преградах. Таким образом, формирование карты местности и выработка управляющего решения должна происходить параллельно с обработкой данных с датчика, а не задерживать этот процесс. Особенно это важно при карте местности значительных размеров.

Если помимо того, чтобы избегать столкновений, на робота будет возложена дополнительная задач, например, пройти лабиринт, алгоритм движения робота значительно усложнится. 

\paragraph{Пример программы управления радиолокатором}
\label {ex:rls_system}
Ниже в иллюстративных целях приводится иерархическая структура типичной программы управления наземным радиолокатором. Из Рис.~\ref{ris:rls_system} видно, что реальные программные управляющие системы имеют сложную иерархическую структуру. Алгоритмы, указанные на рисунке, должны функционировать параллельно друг с другом. Программное обеспечение, в свою очередь, разбито на модули, которые взаимодействуют между собой. Вместе программа представляет собой полноценную систему, функционирующую как единое целое. В рамках задачи управления радиолокатором каждый модуль и алгоритм в отдельности не может обходиться без другого.

\begin{figure}[h]
\center{\includegraphics[width=0.75\linewidth]{rls_system}}
\caption{Состав программ управления радиолокатором.}
\label{ris:rls_system}
\end{figure}

В качестве аппаратной платформы для функционирования такого рода программного обеспечения используются вычислительные средства специального назначения. Обработка радиолокационной информации, поступающей с большой частотой, реализуется средствами высокопроизводительных блоков с сигнальными процессорами или программируемых логических интегральных схем (ПЛИС). Непосредственно же алгоритмы управления могут быть реализованы на базе операционных систем реального времени, таких как QNX, RTEMS, VxWorks, в виде программы на языке высокого уровня. Параллельность алгоритмов, перечисленных на схеме, обеспечивается средствами данной операционной системы. В качестве языков программирования используются C, C++, которые обеспечивают удобный доступ к аппаратным ресурсам и средствам операционной системы, а также Ada (имеющая встроенную поддержку параллельных операций).

\subsection{Качество управления и алгоритмически-программная реализация}
Точность и устойчивость систем управления при реализации такой системы программными средствами зависит от выбранного алгоритма и качества написанной программы весьма сложным образом. Если в случае механической системы мы, смазывая контактирующие между собой части и таким образом уменьшая трение, можем гарантировать увеличение быстродействия системы, то программа или алгоритм не имеют таких очевидных источников воздействия. Даже увеличение мощности вычислительных средств при нерациональном их использовании не приведет к увеличению быстродействия управляющей системы, не говоря уже об алгоритме, который в ней реализован. Таким образом, оценка точности и устойчивости программных управляющих систем представляет собой сложную задачу.

Для примера рассмотрим простейший случай (см. Рис.~\ref{ris:unstable_ex}). Допустим, управляющая программа получает данные с двух ИК-датчиков $T_{1}, T_{2}$, закрепленных на вращающемся приводе на расстояниии $d$ друг от друга. При этом управляющий алгоритм решает задачу слежения за точкой в пространстве, имеющей наибольшую температуру. При отклонении этой точки привод поворачивается в ту сторону, с которой расположен датчик, измеривший большую температуру, пока она вновь не станет равной у обоих. Таким образом реализуется типичная {\itследящая система} в соответствии со схемой на Рис.~\ref{ris:loop_system}.

\begin{figure}[h]
\center{\includegraphics[width=0.5\linewidth]{unstable_ex}}
\caption{Следящая система с ИК-датчиками.}
\label{ris:unstable_ex}
\end{figure}

Допустим, что данные датчика читаются с частотой $f_1=\frac{1}{\tau}$. Управляющие воздействия на привод подаются с той же частотой $f_2 = f_1$. При этом такой частоты достаточно для устойчивости системы слежения. Всякий раз, когда точка перемещается в пространстве, привод успевает повернуть датчик так, что в следующий момент он снова наблюдает за точкой. 

Угол, на который нужно повернуть привод, при малых рассогласованиях пропорционален разнице температур:
\begin{equation}
\label{eq:ex_unstable1}
\begin{array}{l}
{\Delta}T = T_2 - T_1 \\
{\Delta}{\varphi} = k_{\varphi}{\Delta}T
\end{array}
\end{equation}

В момент $t_i = {\tau}i$ данное рассогласование пересчитывается в напряжение $U = k_{U}{\Delta}{\varphi}$ и передается в подсистему управления приводом.  Привод при этом поворачивается в заданное положение за время $\tau_{1} << {\tau}$.

Допустим, что мы увеличили период выдачи данных на привод за счет программной задержки: $f_2 = \frac{1}{\tau + {\Delta}{\tau}}$. Пусть объект наблюдения перемещается в пространстве так, что угол $\Delta{\varphi}(t)$ изменяется пилообразно:
\begin{equation}
\Delta{\varphi}(t) = \left\{
\begin{array}{ll}
2{\pi}f_{1}t,&0 \le t < {\tau}_0\\
-2{\pi}f_{1}t,&{\tau}_0 \le t < 2{\tau}_0\\
2{\pi}f_{1}t,&2{\tau}_0 \le t < 3{\tau}_0\\
...\\
(-1)^{n}2{\pi}f_{1}t, & (n-1){\tau}_0 \le t < n{\tau}_0
\end{array}
\right\}
\end{equation}

{\it
В качестве упражнения предлагается самостоятельно построить график изменения угла положения объекта наблюдения и управляющего напряжения при следующих исходных данных: $f_{1} = 1$~Гц, $\tau_{0} = 0.5$~с, $k_{\varphi} = 0.1$~рад/К, $k_{U} = 1$~В/рад, $\tau_{1} = 0.05$~с, ${\Delta}\tau = 0.1, 0.5, 1.0$~с.
}

Ясно, что замедление выдачи управляющего воздействия приведет к тому, что привод будет <<отставать>> от объекта наблюдения. Управляющие напряжение будет неактуальным на момент очередного обновления данных с датчиков. 

Внесение задержки как в линию выдачи сигнала, так и в обратную связь приводит к ошибке в системе управления и потери устойчивости. Это говорит о том, что программная реализация имеет жесткие временные ограничения, невыполнение которых приводит к утере работоспособности системы в целом.

\section{Введение в системы реального времени и встраиваемые системы}
В данном разделе речь пойдет об особенностях систем реального времени и встраиваемых систем. Упор будет делаться на программные системы, с которыми мы и будем иметь дело на протяжении всего курса. В предыдущем разделе уже было сказано о важности осуществления, в частности, управления техническими средствами в реальном масштабе времени. Ниже этот аспект раскрывается более формально.

Говоря о встраиваемых системах, мы имеем в виду широкий класс аппаратно-программных систем, примеры которых уже приводились в предыдущем разделе. В каждом из них так или иначе присутствовало некоторое вычислительное средство. Собственно, оно и является аппаратной базой в любой встраиваемой системе, потому что в буквальном смысле {\itвстраивается} в некий комплекс технических средств. При этом главную роль играет программное обеспечение, которое функционирует на базе вычислителя. Мы уже видели, что от качества программной реализации зависит работа системы управления. Далее этот тезис будет развит и конкретизирован.

\subsection{Особенности встраиваемых систем}
Основные свойства встраиваемых систем можно сформулировать следующим образом:
\begin{itemize}
\item своевременность реагирования,
\item параллелизм,
\item живучесть,
\item гетерогенность,
\item реактивность.
\end{itemize}

Ряд данных свойств уже обсуждался в предыдущем разделе. Ниже приводится систематизация и уточнение формулировок, касающихся данных понятий.

\paragraph{Своевременность реагирования.} Реальные вычисления всегда занимают время. Не существует вычислений, которые могут быть сделаны моментально. Время является одним из важнейших вычислительных ресурсов, наряду с памятью.

Современные процессоры и системные программы зачастую используют технологии, которые делают сложным подсчет времени, которое необходимо для осуществления тех или иных вычислительных операций: кеширование данных и инструкций, предсказание поведения программы, <<ленивые>> вычисления, подкачка образа памяти с диска. Часть данных технологий приходится исключить в системах реального времени в силу того, что они могут приводить к непредсказуемым задержкам.

Использование даже самых мощных компьютеров, как показывает история, все равно заставляет разработчиков встраиваемых систем так или иначе учитывать временной фактор.

\paragraph{Параллелизм.} Встраиваемые системы редко взаимодействуют только с одним физическим процессом. Им одновременно приходится реагировать на поступление данных с различных датчиков, и при этом нужно, чтобы оставалось время на вычисления.
{\scriptsize
Пример параллельных операций приводился в предыдущем разделе для мобильного робота и системы управления радиолокатором.
}

Одной из сложностей обеспечения выполнения параллельных операций является разделение ресурсов. Для обеспечения параллелизма в системах реального времени используются потоки (или задачи), семафоры, мониторы и другие примитивы. Они будут подробно рассмотрены в дальнейшем. Однако в сложных программах их часто скрывают за примитивами более высокого уровня. Кроме того, присутствует принципиально иной подход, использующий ПЛИС, где параллельность операций достигается за счет архитектуры самого вычислителя.

Параллелизм во встраиваемых системах является их неотъемлемым свойством, обусловленным необходимостью взаимодействовать с реальным миром.

\paragraph{Живучесть.} Это также одно из фундаментальных свойств встраиваемых систем, о которых уже говорилось. Программа не должна ожидать событий, которые никогда не произойдут. При этом нельзя просто прервать выполнение программы. Типичной ситуацией является <<дедлок>>, когда два вычислительных процесса ожидают результат друг друга.

Отладка программ реального времени, имеющих параллельные вычисления, весьма сложна и зачастую не может быть сделана по шагам, как в обычной программе. Этому будет посвящено отдельный раздел курса.

Помимо всего прочего, правильность работы программы -- это не только верно рассчитанный ответ. Он должен быть получен на нужный момент времени. Вследствие взаимодействия встраиваемых систем с реальными физическими процессами важную роль играет также потребляемая мощность, защита информации и т. д.

\paragraph{Гетерогенность.} Данное свойство подразумевает, что встраиваемая система является смешанной программно-аппаратной системой. Для эффективного функционирования ряда алгоритмов зачастую бывает необходимо реализовать специальную аппаратную платформу, скажем, встроить аппаратные шифраторы, дешифраторы, блоки цифровой обработки информации и другие.

Кроме того, гетерогенность наблюдается и в смешанной обработке синхронных (происходящих через заданные промежутки времени) и асинхронных внешних событий. Это уже касается особенностей программного обеспечения встраиваемой системы.

\paragraph{Реактивность.} Реактивные системы -- это системы, реагирующие на события окружающей среды с тем темпом, который определяет окружающая среда. В противовес реактивных систем можно упомянуть интерактивные системы, которые взаимодействуют с окружающей средой с темпом, который определяют сами, и трансформационные системы, которые просто обрабатывают данные. Реактивные системы работают непрерывно, как физический процесс.

Одним из желаемых свойств реактивных систем является {\itробастность}, подразумевающая способность приспосабливаться к изменению внешних условий. Так, может в широких пределах варьироваться поток информации, а также доступные ресурсы.

\subsection{Понятие реального времени. <<Жесткое>> и <<мягкое>> реальное время}
Наконец, мы готовы дать определение системе реального времени. Формулировки в различной литературе приводятся разные, но в целом они не противоречат друг другу. В данном курсе принимается, что {\it система реального времени -- это совокупность аппаратно-программных средств, гарантирующих выполнение возложенных на них задач в определенный промежуток времени}. Ясно, что встраиваемые системы являются разновидностью систем реального времени. Программные средства АИУС также должны быть системами реального времени.

Введем следующие понятия:
\begin{itemize}
\item {\it дедлайн $T_d$} -- предельный срок выполнения задачи,
\item {\it латентность $T_l$} -- время отклика на внешние события,
\item {\it джиттер $\sigma_t$} -- разброс значений временного отклика.
\end{itemize}

Под системами {\it<<жесткого>> реального времени} понимаются такие, в которых время выполнения задачи $T$ не должно превышать $T_d$. Нарушение этого условия приводит к неработоспособности системы.

Системы {\it<<мягкого>> реального времени} допускают превышения $T_d$, однако это приводит к ухудшению их характеристик.

{
\scriptsize
Более формально можно считать, что в системах <<мягкого>> реального времени матожидание и дисперсия времени выполнения задачи имеет конечную величину:
\begin{equation}
E(T) = \int\limits_{-\infty}^{+\infty}{T\rho(T)dT} < \infty
\end{equation}
\begin{equation}
D(T) = \int\limits_{-\infty}^{+\infty}{(T - E(T))^2\rho(T)dT} < \infty
\end{equation}
где $\rho(T)$ -- ПРВ времени завершения задачи.

Для систем <<жесткого>> времени, в свою очередь:
\begin{equation}
sup(T) = T_d
\end{equation}
}

\subsection{Преимущества и недостатки микропроцессорных систем реального времени}
Микропроцессорные системы реального времени базируются на аппаратных средствах, в которых основные вычислительные и системообразующие алгоритмы возложены на микропроцессор -- относительно универсальный вычислитель последовательного типа, синтезированный на полупроводниковом кристалле. Точнее, последовательным в микропроцессоре является ядро, а ядер может быть несколько. Если говорить о работе микропроцессора в двух словах -- то его функции состоят в выборке из памяти очередной команды и выполнении действия, которое в ней закодировано. Вычисления, кроме того, могут быть прерваны событием извне ({\itпрерыванием}). В этом случае микропроцессор прекращает выполнение текущего потока инструкций и переходит к обработке прерывания.

\begin{figure}[h]
\center{\includegraphics[width=0.75\linewidth]{proc_pict}}
\caption{Внешний вид микропроцессорных чипов и модулей.}
\label{ris:proc_pict}
\end{figure}

К преимуществам систем, основанных на микропроцессорах, следует отнести:
\begin{itemize}
\item{\itУниверсальность}. Вместо того, чтобы производить каждый раз новую аппаратуру для очередной задачи, предпочтительно выпускать унифицированные микропроцессорные модули, которые могут реализовать любую выбранную задачу.
\item{\itНизкое энергопотребление}. Современные микропроцессорные модули потребляют в десятки и сотни раз меньше энергии, чем цифровые системы на базе схем малой интеграции и тем более аналоговых системы. Особенно это важно для встраиваемых систем (и в частности для АИУС).
\item{\itВзаимозаменяемость}. При отсутствии на рынке того или иного микропроцессора не составит труда подобрать аналог, поскольку с алгоритмической точки зрения не важно, для какой архитектуры микропроцессора реализована программа. Перенос ее также более прост, нежели изменение схемотехники.
\item{\itОбновляемость}. Внесение новой функциональности в алгоритм, реализуемый микропроцессорными средствами, либо исправление ошибок сводится к изменению программного обеспечения.
\item{\itДешевизна}. Производство микропроцессоров в наши дни имеет такие широкие промышленные масштабы, что цена одного кристалла составляет от 100 р. при аппаратной мощности как у полноценного компьютера 70-х годов. Кроме этого, микропроцессоры значительно дешевле ПЛИС, хотя и не применимы в некоторых задачах, с которыми ПЛИС легко справляется.
\item{\itРазмеры}. Микропроцессорные модули в наши дни могут занимать объемы порядка единиц см$^3$, что, безусловно, удобно для встраиваемых систем.
\item{\itОтказоустойчивость}. По сравнению с масштабными системами на основе схем малой интеграции отказоустойчивость однажды синтезированного кристалла является очевидной. Аналоговые системы, подверженные ошибкам из-за изменения свойств элементов, также уступают микропроцессорным системам. Кроме того, аналоговые системы приходится индивидуально настраивать, чего не происходит в цифровых и в частности микропроцессорных.
\end{itemize}

Впрочем, не лишены данные системы и недостатков. Прежде всего, это так или иначе ограниченная скорость вычислений. Даже если тактовая частота микропроцессора высока, те или иные вычислительные операции могут совершаться за несколько тактов. Кроме того, обращение к памяти таких микропроцессоров ограничено частотой шины данных. Следующий недостаток -- это принципиально последовательная архитектура, которого лишены, в частности, ПЛИС и аналоговые вычислители. Кроме этого, любые цифровые системы имеют конечную точность, в отличие от аналоговых процессоров, использующих физические явления для интегрирования и дифференцирования. Впрочем, сложные алгоритмы на аналоговых процессорах все равно синтезировать значительно более трудоемко, поэтому они не нашли широкого применения. Также существенным моментом при работе с микропроцессорами является поддержание температурного режима и влажности в допустимых пределах, потому что перегрев кристалла приводит к его выходу из строя. И наконец в космических системах требуется дополнительные средства для защиты от элементарных частиц.

\subsection{Программные системы реального времени без операционных систем}
Наличие микропроцессора уже само по себе позволяет реализовать простейшие системы реального времени <<на железе>> с использованием одного только ассемблера. Более того, в ряде микроконтроллеров (<<легковесная>> микропроцессорная система) до сих пор широко применяется ассемблер. При этом, правда, данные контроллеры чаще всего выполняют транспортные функции либо несложные вычисления. Далее в курсе будyт приведены примеры архитектуры систем реального времени без использования операционной системы. Перечислим их:
\begin{itemize}
\itemБесконечный цикл опроса оборудования в ожидании изменения состояния датчиков или других аппаратных средств.
\itemПрограмма, построенная на обработке прерываний (синхронных и асинхронных).
\itemБесконечный цикл с обработкой очереди сообщений, формируемых по прерываниям.
\itemПрочие архитектуры, использующие комбинацию очередей сообщений, обработки прерываний и вечных циклов.
\end{itemize}

Главной особенностью таких программ является отсутствие развитых средств для выполнения параллельных операций и разделения ресурсов. Однако в ряде задач такие решения применимы и широко используются.

\section{Введение в аппаратную архитектуру встраиваемых систем на базе микропроцессоров}
В данном разделе мы рассмотрим базовые элементы аппаратной архитектуры микропроцессорных встраиваемых систем и их особенности. Общее понятие о таких системах можно получить из предыдущего раздела.
\subsection{Место и роль CPU в микропроцессорных системах}

% Википедия
\textit{CPU (Central Processing Unit)} -- микросхема (или несколько микросхем), отвечающих за реализацию арифметических, логических операций и операций управления, записанных в машинном коде.

% Ершова Н. Ю., Ивашенков О. Н., "Микропроцессоры"
Микропроцессор характеризуется: 
\begin{itemize}
\item тактовой частотой, определяющей максимальное время выполнения переключения элементов;
\item разрядностью, т.е. максимальным числом одновременно обрабатываемых двоичных разрядов.
\end{itemize}

\textit{Микроархитектура} микропроцессора -- это аппаратная организация и логическая структура микропроцессора, регистры, управляющие схемы, арифметико-логические устройства, запоминающие устройства и связывающие их информационные магистрали.

\textit{Макроархитектура} -- это система команд, типы обрабатываемых данных, режимы адресации и принципы работы микропроцессора.

Процессоры с одной и той же макроархитектурой могут иметь различную микроархитектуру. Например, для настольных компьютеров характерна макроархитектура x86 для семейств процессоров Intel Pentium, Intel Celeron, AMD и проч., имеющих различную микроархитектуру.

Существуют следующие разновидности микропроцессоров:
\begin{itemize}
\item CPU для \textit{микроконтроллеров} ($\mu$C) -- маломощных вычислительных средств. CPU в них обычно имеет разрядность 8-16. Периферия в микроконтроллерах представлена памятью, датчиками и тактовыми генераторами. Типичными представителями являются AVR, MIPS, PIC и прочие.
\item \textit{DSP} -- CPU для цифровой обработки сигналов. О их применении будет сказано отдельно далее в курсе при затрагивании вопросов алгоритмов, реализуемых в АИУС. Обычно DSP включают в себя специальные блоки обработки данных, например, быстрого преобразования Фурье, вычисления синуса и косинуса, цифровой фильтрации и т. д. Крупнейший производитель -- Texas Instruments, NEC.
\item \textit{GPU} -- графические процессоры. Применяются для графического рендеринга (отрисовки). Современные GPU поддерживают 3d-графику, шейдинг, цифровое видео. Крупнейшие производители -- Intel, AMD, NVIDIA.
\end{itemize}

Процессоры по системе команд можно классифицировать как RISC и CISC-процессоры. CISC-процессоры имеют расширенный набор инструкций (DSP имеют специальные инструкции, например, для цифровой фильтрации, и являются разновидностью CISC-процессоров). RISC-процессоры (например, SPARC), за счет сокращенного набора инструкций увеличивают быстродействие именно за счет этого: программы легко декодировать а выполнение их происходит за короткий промежуток времени.

Современные процессоры имеют конвейерную обработку. Структура процессора с конвейерной обработкой показана на Рис.~\ref{ris:cpu}.

\begin{figure}[h]
  \center{\includegraphics[width=1\linewidth]{cpu}}  
  \caption{Пример конвейерного микропроцессора}
  \label{ris:cpu}
\end{figure}

Серыми полосками показаны регистры-защелки, данные на которых обновляются по фронту тактового генератора. Они разделяют этапы конвейера между собой.

\textit{Счетчик команд(PC)} вычисляет адрес очередной команды, которая вычитывается из \textit{памяти команд}. В ней хранятся закодированные команды, имеющие размер 32 бита. По фронту тактового генератора к PC прибавляется 4 байта, пока некая условная команда не изменит PC. Декодер извлекает из команды ту часть, которая отвечает за обращение к регистрам и извлекает нужные данные из регистров. На следующем этапе конвейера данные обрабатываются средствами \textit{арифметически-логического устройства (ALU)}. Далее происходит чтение или запись данных в память, в соответствии с содержимым регистров. После этого, на последней стадии, регистры снова перезаписываются по результатам работы ALU.

На каждом такте тактового генератора одновременно может исполняться 5 инструкций, каждая на разной стадии. В этом заключается принцип конвейера.

DSP обычно содержат дополнительные блоки для перемножения, специальные ALU для вычисления адреса и содержат двухканальную память данных для одновременного доступа для двух операторов.

Выше была представлена типовая конвейерная схема CPU. В конкретных случаях она может отличаться для микропроцессоров различных фирм.

\subsection{Аппаратные особенности памяти во встраиваемых системах}
Вопросы организации хранилищ данных играют большую роль во встраиваемых системах. В частности, программист должен выбрать, должны ли данные сохраняться после отключения питания. В связи с этим различают \textit{энергозависимую} и \textit{энергонезависимую} память.

\subsubsection{Энергозависимая память}
В дополнении к файлу регистров, микропроцессорная система, как правило, включает некоторое количество \textit{памяти с произвольным доступом -- RAM}. Статическая RAM (\textit{SRAM}) позволяет обращаться к содержимому быстрее, чем динамическая (\textit{DRAM}), но также больше и по массово-габаритным показателям. DRAM хранит данные короткое время, SRAM -- пока она подключена к питанию. Оба типа памяти теряют содержимое, когда питание отключается, то есть они являются разновидностями энергозависимой памяти.

Большая часть встраиваемых компьтеров содержит SRAM-модуль. Кроме того, часто в них входит также DRAM-модуль, потому что при помощи SRAM-технологии бывает сложно предоставить достаточное пространство хранения данных. При этом следует иметь в виду, какое время занимает обращение к данным, если они хранятся в SRAM или DRAM-памяти. Кроме того, DRAM-память может допускать вариативность времени доступа, поскольку она может быть <<занята>> обновлением состояния, когда к ней обратились из программы. К тому же, <<история>> обращений к DRAM может влиять на длительность очередного обращения. Время, которое затрачивается для доступа к некоторому адресу, зависит от того, к какому адресу в последний раз обращались.

Производители DRAM-памяти обычно документируют тот факт, что каждый участок памяти следует обновлять, скажем, каждые 64 мс, и что набор участков (<<ряд>>) обновляются совместно. Сам факт чтения содержимого памяти обновит все участки, которые прочитаны (и в этом же ряду), но в силу того, что приложение врядли обратится ко всем рядам в заданные интервал, DRAM обслуживается дополнительным контроллером, который производит обновление всех расположений для сохранения данных. \textit{Контроллер памяти} будет замедлять обращение к памяти, если он занят обновлением расположений памяти. Это и приводит к вариативности доступа к DRAM-памяти.

\subsubsection{Энергонезависимая память}
На ранних этапах развития вычислительных систем энергонезависимая память представляла собой магнитную ленту.

Простейший вид энергонезависимой памяти -- \textit{простоянное запоминающее устройство: ПЗУ, ROM}. Ее содержимое определяется конфигурацией микросхемы. Это подходит, когда нужно просто хранить константные данные в массовом производстве устройств. Такие программы называются также \textbf{firmware} (как бы в противоположность \textbf{software}). Существует несколько видов памяти, которые могут быть использованы таким образом, помимо ROM-микросхем:
\begin{itemize}
\item \textit{EEPROM} -- <<электрически-стираемая>> программируемая ROM. Количество записей в такую память ограничено и занимает значительно больше времени, чем чтение;
\item \textit{Flash} -- энергонезависимая память, также имеющая ограниченное количество актов записи, и при это достаточно быстрое время чтения (конечно, медленнее, чем SRAM и DRAM). Поэтому часто используемые данные лучше всего скопировать из Flash-памяти в RAM. Время записи также достаточно велико. Разновидности: \textit{NOR} и \textit{NAND}-память.

{\scriptsize
Принипы действия EEPROM- и Flash-памяти основаны на использовании больших массивов полупроводников (полевых транзисторов). При записи они определенным образом накапливают заряд, при чтении его можно регистрировать.}
\item \textit{Дисковая память}. Данный вид памяти также является энергонезависимым и хорошо знаком из работы с настольными компьютерами. Доступ к такому виду памяти может быть достаточно длительным, поскольку требуется время на перевод головки диска в нужное состояние и вращение диска. Кроме того, диски неустойчивы к механическим воздействиям и вибрациям, что приводит к их неприменимости в ряде встраиваемых систем.
\end{itemize}

\subsubsection{Карта памяти}
\textit{Картой памяти} в процессоре называется сопоставления определенного диапазона адресов внешним устройствам. Полный размер адресного пространства, скажем, для 32-битного процессора, составляет $2^{32}$ ячейки памяти или 4 гигабайта, если предполагать, что каждый адрес относится к одному байту. Разрядность адреса обычно соответствует машинному слову, кроме 8-битных процессоров, где разрядность адреса обычно больше (16 бит). Пример карты памяти для ARM Cortex$^{TM}$ приводится на Рис.~\ref{ris:mmap}. 

В данной архитектуре память программы и память данных разделена между собой. То есть код программы хранится отдельно от данных. Это называется \textbf{Гарвардской архитектурой}. В \textbf{Фон-Неймановской архитектуре} программа и данные хранятся в одной и той же памяти (схемотехнически). Так устроено большинство персональных компьютеров.
\begin{figure}[h]
  \center{\includegraphics[width=0.5\linewidth]{mmap}}  
  \caption{Пример карты памяти}
  \label{ris:mmap}
\end{figure}

Обращение к адресам памяти, относящимся к периферии, используется для обмена данными с соответствующим устройством. В частности, в ОС DOS, где программа имела доступ ко всему адресному пространству в том виде, как это представлено на Рис.~\ref{ris:mmap}, для вывода пиксела на экран нужно было записать определенное значение в память видеоадаптера.

\subsubsection{Файлы регистров}
Наиболее интегрированна с CPU память, имеющая название \textit{регистровый файл}. Каждый регистр в этом файле содержит \textit{слово}. Разрядность слова -- одна из основных характеристик процессора. Файл регистров может быть реализован чисто схемотехнически при помощи триггеров, либо помещен в SRAM.

Количество регистров в процессоре, как правило, мало. Это связано с дороговизной такого типа памяти, и, кроме того, информационной ценности каждого бита в коде команды процессору. Если в регистровом файле содержится 16 регистров, на кодирование обращения к каждому из них нужно 4 бита. Если каждая команда может работать с тремя регистрами, то таким образом, нужно 12 бит для их адресации. Если аппаратное слово составляет 16 бит, то остается всего 4 бита дополнительной информации.

\subsection{Взаимодействие с внешними устройствами. Прерывания}
\textit{Прерывание} -- это механизм для осуществления остановки выполнения инструкций процессора, что бы он ни делал, и замена их на определенный заранее код, называемый \textit{обработчик прерывания}. Три типа событий могут стать источниками прерывания. Во-первых, это прерывание от оборудования. При этом некоторое внешнее устройство меняет уровень напряжения линии прерывания. В случае <<софтверного>> прерывания выполняющаяся на процессоре программа записывает в его регистр, отображенный в ее память, некоторое специальное значение. Третий случай -- \textit{исключение}, вызванное ошибкой программы.

В первых двух случаях по окончании обработки прерывания программа обычно возобновляет свою работу. В третьем, как правило, она прерывается, устанавливая счетчик PC в фиксированное значение, так, чтобы операционная система могла прервать неправильно работающую программу.

Для обработки прерывания его нужно прежде всего разрешить. Разрешаются они индивидуально и механизм зависит от конкретного процессора. Прерывания и исключения имеют, как правило, приоритеты. Прерывания с наивысшим приоритетом не могут остановить выполнение процедуры обработки прерывания с высшим. Как правило, исключения имеют наивысший приоритет и их обработчик выполняется всегда.

Обработка прерывания, как правило, заключается во-первых, в запрете других прерываний, затем -- записи счетчика PC и регистров статуса процессора в стек, а затем -- выполнении инструкций по определенному адресу, который обычно содержит оператор безусловного перехода к обработчику прерывания. Обработчик прерывания должен сохранить в стеке любые на данный момент используемые значения, а затем их восстановить. Также после обработки прерывания они должны вновь быть разрешены.

Важно отметить, что обработчик прерывания может обращаться к глобальным областям памяти и менять их, <<разрывая>> последовательность действий программы, которая выполняется на процессоре. Говорят, что операции, между которыми значение переменной может измениться, называются атомарными. Тем не менее, бывает сложно понять, какие операции атомарные и в самом деле. Это еще как-то возможно на ассемблере, но чрезвычайно сложно на C. Простейший оператор присваивания может оказаться неатомарным:
\begin{lstlisting}
timer_count = 1000;
\end{lstlisting}

На 8-битном микроконтроллере, скажем, данная инструкция может занимать более одного такта (поскольку 1000 занимает больше 8-ми бит). Допустим, обработчик прерывания также пишет в переменную \textit{timer\_count}. В этом случае, конечное значение в переменной будет комбинацией того значения, которое было записано в обработчике и того, что было записано выше. В конце концов, \textit{timer\_count} будет отличаться как от 1000, так и от числа, записаного в обработчике. Подобный случай вряд ли случится на 32-битном микроконтроллере.

Для этой цели прибегают к дополнительным средствам защиты общей памяти, например, мутексам. Это будет обсуждаться в курсе дальше.

На схемотехническом уровне за управление прерываний в микропроцессорной системе отвечает \textbf{контроллер прерываний}. Каждому прерыванию соответствует \textit{вектор прерываний}, который является адресом обработчика прерываний или индексом массива, называемом \textit{таблицей векторов прерываний}.

Прерываний бывают двух видов: \textit{по уровню} и \textit{по фронту}. В первом случае напряжение на линии прерывания держится до тех пор, пока его не снимут вынужденно, во втором -- достаточно короткого момента, когда меняется уровень напряжения, чтобы оборудованию стало о нем известно. На схемотехническом уровне это решается схемой с открытым коллектором.

Когда линий прерывания не хватает, их делят несколько прерываний (в том числе по схеме с открытым коллектором).

\subsection{Ввод-вывод в микропроцессоре}
Для ввода-вывода процессоры во встраиваемых системах используют пины ввода-вывода (general-purpose I/O pins). Они позволяют программе читать или устанавливать уровень напряжения на <<ножках>> процессора (определенных). Естественно, уровни напряжения представлены логическим нулем или единицей.

Допустим, что напряжение питания для процессора $V_{DD}$. Тогда логическая единица на пинах будет примерно $V_{DD}$, а логический ноль -- около нуля. В инверсной логике данные уровни инвертированы.

В процессорах, как правило, присутствует особый регистр конфигурирования портов ввода-вывода. Записав в него конфигурацию определенных пинов как выходных, в них можно устанавливать напряжение путем записи в другой регистр. Таким образом, программа может контролировать оборудование напрямую.

При этом следует следовать спецификациям внешних устройств. Выходной ток:
\begin{equation}
I = \frac{V_{DD}}{R}
\end{equation}
может превысить допустимое значение. Таким образом, процессор и внешние устройства, сообщающиеся с ним через пины, должны иметь \textit{гальваническую развязку}.

Кроме того, внешние устройства могут создавать шумовые воздействия на входах процессора или в цепи питания процессора. Входы процессора должны содержать \textit{триггер Шмидта}. Внешние устройства могут функционировать в совершенно отличном от процессора режиме (по мощности). Это опять же требует наличия изоляции между процессором и внешними устройствами.

\begin{figure}[ht]
  \center{\includegraphics[width=0.5\linewidth]{open_col}}  
  \caption{Открытый коллектор}
  \label{ris:open_col}
\end{figure}

Выходные пины обычно содержат схему с открытым коллектором (Рис.~\ref{ris:open_col}). Запись логической единицы в регистр приводит к открыванию транзистора и снижению напряжения в цепи коллектора, 0 -- к закрыванию и повышению уровня напряжения до $V_{DD}$. Соединение каскадов в открытым коллектором параллельно требует наличия \textit{подтягивающего резистора}. При этом такая цепочка реализует схему NAND в прямой (не инверсной) логике.

Помимо логического нуля и единицы выходной пин может быть и вовсе отключен (состояние Z) -- tristate-логика.

\subsection{Аналогово-цифровой интерфейс}
Аналоговый сигналы изменяются непрерывно по своей природе. Цифровые сигналы дискретны. Простейшее аналогово-цифровое преобразование осуществляется компаратором по уровню:
\begin{equation}
q(t) = \left\{
\begin{array}{ll}
0, & x > 0 \\
1, & x \le 0 \\
\end{array}
\right\}
\end{equation}

Данный сигнал называется \textit{квантованным}. Если мы будем снимать его с определенным периодом по времени $T$, он будет уже \textit{цифровым}:
\begin{equation}
y(n) = q(nT)
\end{equation}

Устройство, осуществляющее аналогово-цифровое преобразование (АЦП), характеризуется периодом дискретизации и количеством разрядов на выходе. Для компаратора это один разряд.

Обратная операция осуществляется цифро-аналоговым преобразователем (ЦАП).

Проектирование АЦП и ЦАП выходит за рамки данного курса. Следует, однако, упомянуть, что существуют подходы к данным вопросам (теорема Котельникова, критерий Найквиста), определяющие оптимальный период квантования для представления непрерывной функции дискретными отсчетами в зависимости от ширины ее спектра.

 \subsection{Шинная архитектура}
 Шинная архитектура представляет собой организацию взаимодействия между аппаратными блоками микропроцессорной системы посредством присоединения нескольких блоков к одному набору проводников. 
 
Обмен данными по шинам может производиться \textit{параллельно} и \textit{последовательно}. Последовательная передача данных предполагает передачу одного бита в каждый из промежутков. времени. Параллельная, в свою очередь -- нескольких бит.	 Последовательные шины чаще используются там, где проще провести один провод, нежели несколько. Передача данных при этом делается более надежной. В свою очередь, параллельная шина отличается по определению более быстрой потенциальной передачей данных, чем последовательная.

Примеры шин можно видеть на Рис.~\ref{ris:bus}: PCI (peripheral component interface), ISA (industry standard architecture), SCSI (small computer system interface). В промышленности также распространена шина VME (внутренний конструктив) и IEEE-488. Широко известна шина USB (Universal Serial Bus). CAN-шина (controller area network) широко используется в автомобилестроении.

\begin{figure}[h]%Танненбаум
  \center{\includegraphics[width=0.7\linewidth]{bus}}  
  \caption{Шинная архитектура в Pentium}
  \label{ris:bus}
\end{figure}

В силу того, что шина <<раздается>> между несколькими устройствами, она должна включать \textit{механизм контроля доступа} (MAC -- media-access control). В простейшем случае -- это один контроллер шины и несколько оконечных устройств. Контроллер пишет, оконечные устройства читают. Другой способ -- переключение времен записи для различных устройств. Следующий способ -- т. н. <<token ring>> -- маркер записи. Когда станция владеет им, она может передавать информацию. По окончанию передачи она возвращает его в среду, так, что передавать информацию могут другие станции. Следующий механизм -- использование арбитра шины, управляющего передачей в соответствии с приоритетом оконечников. Другой механизм -- collision sense multiply access (CSMA), когда устройства просто начинают передавать данные, определяют коллизию, и повторяют передачу данных в случае коллизии.

В различных видах шин широко применяется механизм DMA -- direct memory access, когда внешнее получает доступ к памяти процессора (при разрешении такого доступа), в частности, при работе по ISA (иногда и PCI). Для передачи данных при этом используется контроллер DMA. В новых устройствах он может отсутствовать.

\subsection{Особенности многопроцессорных систем}
Многопроцессорные системы являются логическим продолжение однопроцессорных систем. 

\subsubsection{Массивно-параллельные компьютеры}
%http://umk.portal.kemsu.ru/mps/html/node1_3.htm
Идея построения компьютеров этого класса тривиальна (см. Рис.~\ref{ris:multi_proc1}): возьмем серийные микропроцессоры, снабдим каждый своей локальной памятью, соединим посредством некоторой коммуникационной среды - вот и все. Достоинств у такой архитектуры масса: если нужна высокая производительность, то можно добавить еще процессоров; если ограничены финансы или заранее известна требуемая вычислительная мощность, то легко подобрать оптимальную конфигурацию и т.п.

Однако есть и решающий "минус", сводящий многие "плюсы" на нет. Дело в том, что межпроцессорное взаимодействие в компьютерах этого класса идет намного медленнее, чем происходит локальная обработка данных самими процессорами. Именно поэтому написать эффективную программу для таких компьютеров очень сложно, а для некоторых алгоритмов – иногда просто невозможно.

\begin{figure}[h]
  \center{\includegraphics[width=0.5\linewidth]{multi_proc1}}  
  \caption{Массиво-параллельный компьютер}
  \label{ris:multi_proc1}
\end{figure}

\subsubsection{Компьютеры с общей памятью}
Вся оперативная память таких компьютеров разделяется несколькими одинаковыми процессорами (см. Рис.~\ref{ris:multi_proc2}). Это снимает проблемы предыдущего класса, но добавляет новые - число процессоров, имеющих доступ к общей памяти, по чисто техническим причинам нельзя сделать большим.

\begin{figure}[h]
  \center{\includegraphics[width=0.5\linewidth]{multi_proc2}}  
  \caption{Массиво-параллельный компьютер}
  \label{ris:multi_proc2}
\end{figure}

Наличие общей памяти значительно упрощает взаимодействие процессоров между собой, однако за этой кажущейся простотой скрываются большие проблемы, присущие системам этого типа. Помимо хорошо известной проблемы конфликтов при обращении к общей шине памяти возникла и новая проблема, связанная с иерархической структурой организации памяти современных компьютеров. Дело в том, что самым узким местом в современных компьютерах является оперативная память, скорость работы которой значительно отстала от скорости работы процессора. В настоящее время эта скорость примерно в 20 раз ниже требуемой для 100\% согласованности со скоростью работы процессора, и разрыв все время увеличивается. Для того, чтобы сгладить разрыв в скорости работы процессора и основной памяти, каждый процессор снабжается скоростной буферной памятью (кэш-памятью), работающей со скоростью процессора. В связи с этим в многопроцессорных системах, построенных на базе таких микропроцессоров, нарушается принцип равноправного доступа к любой точке памяти. Для его сохранения приходится организовывать аппаратную поддержку \textbf{когерентности кэш-памяти}, что приводит к большим накладным расходам и сильно ограничивает возможности по наращиванию производительности таких систем путем простого увеличения числа процессоров.
%http://umk.portal.kemsu.ru/mps/html/node1_3.htm - конец

\section{Введение в архитектуру программного обеспечения}
В данном разделе вкратце описывается архитектура встраиваемых программ в основном на уровне системного ПО. Дается определение и примеры операционных систем реального времени. Вводится понятие кросс-разработки и приводятся особенности отладки программ в реальном времени.

 \subsection{Роль прикладного и системного программного обеспечения}
Как известно из курса информатики, программы условно можно разделить на прикладные и системные. Прикладные обеспечивают выполнение конкретной задачи, будь то редактирование текста или обработка сигналов. Системные предназначены для поддержания работы прикладных и только. К ним относится, в частности, сама операционная система, драйверы, вспомогательные утилиты. 

% Танненбаум
Схематично основные рассматриваемые здесь компоненты представлены на Рис.~\ref{ris:os}. В нижней части рисунка показано аппаратное обеспечение. Над аппаратным обеспечением находится программное обеспечение. Большинство компьютеров имеет два режима работы: режим ядра и режим пользователя. Операционная система -- наиболее фундаментальная часть программного обеспечения, работающая в режиме ядра (этот режим называют еще режимом супервизора). В этом режиме она имеет полный доступ ко всему аппаратному обеспечению и может задействовать любую инструкцию, которую машина в состоянии выполнить. Вся остальная часть программного обеспечения работает в режиме пользователя, в котором доступно лишь подмножество инструкций машины. В частности, программам, работающим в режиме пользователя,  запрещено использование инструкций, управляющих машиной или осуществляющих операции ввода-вывода.
\begin{figure}[h] % Танненбаум
  \center{\includegraphics[width=0.5\linewidth]{os}}  
  \caption{Место системного программного обеспечения}
  \label{ris:os}
\end{figure}

Архитектура большинства компьютеров (система команд, организация  памяти, ввод-вывод данных и структура шин) на уровне машинного языка машины слишком примитивна и неудобна для использования в программах, особенно это касается систем ввода-вывода. Чтобы перевести разговор в конкретное русло, рассмотрим, как осуществляется ввод-вывод данных при использовании гибкого диска, если при этом применяются микросхемы, совместимые с контроллером NEC PD765, устанавливаемом на большинстве персональных компьютеров с  процессором производства корпорации Intel. В примере  используется гибкий диск, поскольку он хотя и выходит из употребления, но все же намного проще современного жесткого диска. Контроллер PD765 имеет 16 команд, каждая из которых задается путем загрузки в регистр устройства от 1 до 9 байт.  Эти команды служат для чтения и записи данных, перемещения блока головок и форматирования дорожек, а также для инициализации, считывания параметров, перезапуска и калибровки контроллера и подключенных к нему устройств.  Основными являются команды чтения — read и записи — write, каждая из  которых требует 13 параметров, упакованных в 9 байт. Эти параметры определяют такие вопросы, как адрес считываемого блока на диске, количество секторов на дорожке, режим записи, используемый на физическом носителе, промежуток между  секторами и что нужно делать с адресной меткой удаленных данных. Если эти тонкости вам непонятны, не стоит переживать: перечисляя их, я и хотел показать, что они  понятны лишь посвященным. Когда операция завершится, микросхема контроллера возвращает 23 поля состояния и ошибок, упакованные в 7 байт. Если и этого мало, то можно сказать, что специалист, программирующий работу с гибким диском,  должен постоянно знать, включен или выключен двигатель дисковода. Если двигатель выключен, то его нужно включить (с продолжительным выжиданием времени на раскрутку) перед тем, как данные могут быть считаны или записаны. Но двигатель не может быть включен слишком долго, поскольку это приводит к износу гибкого диска. Таким образом, программист вынужден считаться с издержками длительных ожиданий раскрутки в противовес издержкам, связанным с износом гибких дисков (и утратой записанных на них данных).  Даже не вникая в реальные подробности, можно понять, что обычный  программист, скорее всего, не захочет столь глубоко внедряться в программирование работы с гибкими дисками (или с жесткими дисками, что еще сложнее). Скорее всего, он захочет иметь дело с простой, высокоуровневой абстракцией. Если речь идет о дисках, то обычная абстракция может заключаться в том, что диск содержит коллекцию именованных файлов. Каждый файл может быть открыт для чтения или записи, затем прочитан или записан, после чего он может быть закрыт. А такие  подробности, как текущее состояние двигателя или использование при записи  модифицированной частотной модуляции, не должны фигурировать в той абстракции, которая предоставляется прикладному программисту.  

Абстракция — это ключ к управлению сложностью. Хорошая абстракция  превращает практически неподъемную задачу в две, решить которые вполне по силам.  Первая из этих задач состоит в определении и реализации абстракций. А вторая — в использовании этих абстракций для решения текущей проблемы. Одна из абстракций, понятная практически любому пользователю компьютера, — это файл. Он представляет собой полезный объем информации, скажем, цифровую фотографию, сохраненное сообщение электронной почты или веб-страницу  Работать с фотографиями, сообщениями электронной почты и веб-страницами намного легче, чем с особенностями дисков, продемонстрированными в ранее описанном случае с гибким диском. Задача операционной системы заключается в создании хорошей абстракции, а затем в реализации абстрактных объектов, создаваемых в рамках этой абстракции, и в управлении ими. В этой книге абстракциям будет уделено весьма большое внимание, поскольку они являются одним из ключей к  пониманию операционных систем. 

Представление о том, что операционная система главным образом предоставляет абстракции для прикладных программ, — это взгляд сверху вниз. Сторонники альтернативного взгляда, снизу вверх, придерживаются того мнения, что операционная система существует для управления всеми частями сложной системы. Современные компьютеры состоят из процессоров, памяти, таймеров, дисков, мышей, сетевых интерфейсов, принтеров и широкого спектра других устройств.  Сторонники альтернативного взгляда считают, что задача операционной системы заключается в обеспечении упорядоченного и управляемого распределения  процессоров, памяти и устройств ввода-вывода между различными программами, претендующими на их использование. 
% Танненбаум -- конец

\subsection{Особенности операционных систем реального времени}
Операционная Система реального времени (СРВ) – это система, правильность функционирования которой зависит не только от логической корректности вычислений, но и от времени, за которое эти вычисления производятся. Время выполнения при этом должно быть предсказуемым.

Введем понятие \textit{процессов} и \textit{потоков (нитей)}. Процесс -- это объект операционной системы, с которым связаны некоторые ресурсы. К ним относится оперативная память, дискрипторы открытых файлов и проч. Поток (нить) -- это последовательность инструкций, выполняющихся параллельно. Они существуют внутри процесса.

\textit{Ядро} операционной системы -- это программа, которая осуществляет основные системные функции. В зависимости от масштабов ядра они могут отличаться. В ОСРВ на ядро возложены главным образом следующие функции:
\begin{itemize}
\itemуправление прерываниями,
\itemуправление системным временем,
\itemсоздание, удаление и планирование потоков(нитей).
\end{itemize}

% http://dvo.sut.ru/libr/skiri/i277zaru/ob.htm
Требования, предъявляемые ОС при проектировании ОСРВ:
\begin{enumerate}
\itemОС должна быть многонитевой (multi-threaded) и прерываемой. Как указывалось выше, ОСРВ должна быть предсказуемой, что означает максимальное время выполнения того или иного действия, которое должно быть известно заранее и должно соответствовать требованиям приложения.  Первое требование состоит в том, что ОС должна быть многонитевой по принципу абсолютного приоритета (прерываемой). Планировщик должен иметь возможность прервать любую нить и предоставить ресурс той нити, которой он более необходим. ОС (и аппаратура) должны также обеспечивать прерывания на уровне обработки прерываний.
\itemДолжно существовать понятие приоритета нити. Проблема в том, чтобы определить, какой задаче требуется ресурс. В идеальной ситуации ОСРВ отдает ресурс нити или драйверу с ближайшим крайним сроком (так называемые ОС, управляемые временным ограничением (deadline driven OS)). Чтобы реализовать это, ОС должна знать время, требуемое каждой из выполняющихся нитей для завершения (до сих пор не существует ОС, построенной по этому принципу, так как он слишком сложен для реализации), поэтому разработчики ОС принимают иную точку зрения: вводится понятие уровня приоритета задачи, и временные ограничения сводят к приоритетам. Так как умозрительные решения чреваты ошибками, показатели СРВ при этом снижаются. Чтобы более эффективно осуществить указанное преобразование ограничений, проектировщик может воспользоваться теорией расписаний или имитационным моделированием, хотя и это может оказаться бесполезным. На сегодняшний день не имеется иного решения, поэтому понятие приоритета нити необходимо.
\itemОС должна обеспечивать предсказуемые механизмы синхронизации задач. Задачи разделяют данные (ресурсы) и должны сообщаться друг с другом, следовательно, должны существовать механизмы блокирования и коммуникации.  
\itemДолжна существовать система наследования приоритетов. На самом деле, именно этот механизм синхронизации и тот факт, что различные нити используют одно и то же пространство памяти, отличают нити от процессов. Процессы не разделяют одно и то же пространство памяти. Так, например, старые версии UNIX не являются многонитевыми. Старый UNIX – многозадачная ОС, где задачами являются процессы, которые сообщаются через потоки (pipes) и разделяемую память. Оба эти механизма используют файловую систему, а ее поведение непредсказуемо.

Комбинация приоритета нити и разделение ресурсов между ними приводит к другому явлению: классической проблеме инверсии приоритетов. Это можно проиллюстрировать на примере, где есть, как минимум, три нити. Когда нить низшего приоритета заняла ресурс, разделяемый с нитью высшего приоритета, а сначала выполняется нить среднего приоритета, выполнение нити высшего приоритета будет приостановлено, пока не освободится ресурс и не отработает нить среднего приоритета. В этой ситуации время, необходимое для завершения нити высшего приоритета, зависит от нижних приоритетных уровней, – это и есть инверсия приоритетов. Ясно, что в такой ситуации трудно выдержать ограничение на время исполнения.

Чтобы устранить такие инверсии, ОСРВ должна допускать наследование приоритета, т. е. повышение приоритета до уровня вызывающей нити. Наследование означает, что блокирующая ресурс нить наследует приоритет блокируемой нити (справедливо лишь в том случае, если блокируемая нить имеет более высокий приоритет).

Иногда утверждают, что в грамотно спроектированной системе такая проблема не возникает. В случае сложных систем с этим нельзя согласиться. Единственный способ решения этой проблемы состоит в увеличении приоритета нити вручную прежде, чем ресурс окажется заблокированным – это возможно в случае, когда две нити разных приоритетов претендуют на один ресурс. В общем случае решения не существует.

\itemПоведение ОС должно быть известно. Наконец, следует рассмотреть временные ограничения. Времена выполнения системных вызовов и временные характеристики поведения системы в различных обстоятельствах должны быть известны разработчику, поэтому производитель ОСРВ должен приводить следующие характеристики:
\begin{itemize}
\itemлатентную задержку прерывания (т. е. время от момента прерывания до момента запуска задачи): она должна быть предсказуема и согласована с требованиями приложения. Эта величина зависит от числа одновременно <<висящих>> прерываний;
\itemмаксимальное время выполнения каждого системного вызова (должно быть предсказуемым и независимым от числа объектов в системе);
\itemмаксимальное время маскирования прерываний драйверами и ОС.
\itemсистемные уровни прерываний;
\itemуровни прерываний драйверов устройств, их временные характеристики и т. д.
\end{itemize}
\end{enumerate}

Когда все указанные характеристики ОС известны, можно представить разработку СРВ на ее базе с учетом возможностей выбранной ОСРВ и аппаратуры.
% http://dvo.sut.ru/libr/skiri/i277zaru/ob.htm -- конец

Примеры операционных систем реального времени:
% Википедия
\begin{itemize}
\item\textbf{QNX} (произносится как "кью-эн-экс") -- POSIX-совместимая операционная система реального времени, предназначенная преимущественно для встраиваемых систем. Считается одной из лучших реализаций концепции микроядерных операционных систем. 

Как микроядерная операционная система, QNX основана на идее работы основной части своих компонентов, как небольших задач, называемых сервисами. Это отличает её от традиционных монолитных ядер, в которых ядро операционной системы — одна большая программа, состоящая из большого количества «частей», каждая со своими особенностями. Использование микроядра в QNX позволяет пользователям (разработчикам) отключить любую ненужную им функциональность, не изменяя ядро. Вместо этого можно просто не запускать определённый процесс.

Система достаточно небольшая, чтобы в минимальной комплектации уместиться на одну дискету, вместе с этим она считается очень быстрой и должным образом «законченной» (практически не содержащей ошибок).

QNX Neutrino, выпущенная в 2001 году, перенесена на многие платформы, и сейчас способна работать практически на любом современном процессоре, используемом на рынке встраиваемых систем. Среди этих платформ присутствуют семейства x86, MIPS, PowerPC, а также специализированные семейства процессоров, такие, как SH-4, ARM, StrongARM и xScale.

Система платная, при этом для некоммерческого использования и для обучения она предлагается бесплатно.
\item\textbf{RTLinux} -- микроядерная операционная система жёсткого реального времени, которая выполняет Linux как полностью вытесняемый процесс. Работы над RTLinux завершились в 2007 году и на основе наработок этой ОС стартовал проприетарный проект Wind River.

Разработчики RTLinux пошли по тому пути, который предусматривает запуск из наноядра реального времени ядра Linux как задачи с наименьшим приоритетом. В RTLinux все прерывания обрабатываются ядром реального времени, которое включает собственный планировщик задач, обработчик прерываний и библиотечный код. В случае отсутствия обработчика реального времени для какого-то прерывания, оно передаётся в Linux. Фактически Linux является простаивающей (idle) задачей ОСРВ, запускаемой только в том случае, если никакая задача не исполняется в реальном времени. При этом на Linux-задачу накладываются некоторые ограничения, которые, впрочем, прозрачны для программиста.

Ключ к реализации данной системы — эмулирующий систему управления прерываниями драйвер, к которому обращается Linux при попытке блокировать прерывания. В этом случае драйвер перехватывает запрос, сохраняет его и возвращает управление Linux.

Все аппаратные прерывания перехватываются ядром ОСРВ. Когда происходит прерывание, ядро RTLinux решает, что делать. Если это прерывание должно быть обработано обработчиком реального времени, то ядро вызывает соответствующий обработчик. В противном случае или если обработчик реального времени говорит, что хочет разделять это прерывание с Linux, обработчику присваивается состояние ожидания (pending). Если Linux потребовал разрешить прерывания, то прерывания, которые находятся в состоянии ожидания, эмулируются.
\item\textbf{VxWorks} -- операционная система реального времени, разрабатываемая компанией Wind River Systems (США), ориентированная на использование во встраиваемых компьютерах, работающих в системах жёсткого реального времени.

Как и большинство других ОС реального времени, VxWorks включает в себя многозадачное ядро с вытесняющим планировщиком и быстрым откликом на прерывания, средства межпроцессного взаимодействия и синхронизации, а также файловую систему и сетевую подсистему (стек протоколов TCP/IP). В комплект поставки входят средства для кросс-компиляции, мониторинга производительности (WindView), удалённой символьной отладки, а также эмуляции различных процессоров. Дополнительно поставляется значительное количество различных стеков протоколов, графических подсистем и др. как от самой Wind River Systems, так и от третьих фирм. Множество поддерживаемых VxWorks встраиваемых платформ является одним из самых обширных среди операционных систем реального времени.
\item\textbf{RTEMS} (англ. Real-Time Executive for Multiprocessor Systems, рус. Исполнитель реального времени для мультипроцессорных систем) -- свободная операционная система реального времени с открытым исходным кодом, разработанная для встраиваемых систем.

Не предусматривает процессов и зачастую файловой системы. Сертифицирована для использования в авиации и космических исследованиях.
\end{itemize}
% Википедия -- конец

\subsection{Ключевые моменты кросс-разработки для встраиваемых систем}
Кросс-компиляция представляет собой процесс сборки программы для целевой (target) платформы на инструментальной (host). Для осуществления этого процесса существует специальная версия компилятора, который позволяет на выходе получить исполняемые файлы и библиотеки именно в том виде, в котором они могут быть использованы на target-платформе. 

Для конкретики рассмотрим средства кросс-компиляции для QNX.

Разработчик системы предоставляет для программирования под QNX инструменты для сборки программ в QNX, Linux и Windows: объединенный пакет программ QNX Momentics Development Suite. Кросс-компиляция, ясное дело, осуществляется на базе Windows и Linux-версий Momentics. В его состав входит:
\begin{itemize}
\itemСреду разработки (IDE) на базе Eclipse, позволяющую группировать файлы исходного текста, редактировать их и запускать процесс создания программ.
\itemПрепроцессор, компилятор и редактор связей на базе GCC (GNU Compiler Collection). Программы для QNX можно писать на C, C++ и Ada. Соответственно, имеются версии данных продуктов для каждого из языков.
\begin{scriptsize}
Из семинаров должно быть известно, что препроцессор -- это программа, которая обрабатывает исходный текст до компиляции с осуществлением замены тех или иных блоков текста и включением одних файлов в другие. Компилятор производит превращение исходного текста вначале в ассемблерный (эта стадия может отсутствовать), затем в бинарный код, а редактор связей собирает из отдельных модулей бинарного кода исполняемый файл или библиотеку.
\end{scriptsize}
\itemСистему автоматической сборки GNU Make -- программу, которая выполняет те или иные действия в случае изменения даты файлов исходного текста. GNU Make и сценарии автоматизированной сборки будут рассмотрены на семинарах и далее в курсе.
\itemОтладчик GNU Debug и средства удаленной отладки на целевой платформе. Данный продукт будет подробно рассмотрен ниже.
\itemСредство удаленного доступа к графическому интерфейсу на целевой машине -- Phindows.
\itemСредства доступа к файловой системе целевой машины и мониторинга ее состояния на базе сети QNET (разворачивается на транспортном уровне стека OSI -- open systems interconnection basic reference model, то есть на том же, что и TCP/IP, параллельно с ним в сетях Ethernet).
\end{itemize}

\subsection{Особенности отладки для встраиваемых систем}

Встраиваемые системы имеют, как правило, средства разработки, предоставляющие возможность удаленной отладки. В частности, gdb имеет возможность отлаживать программы по Ethernet по определенному порту (по умолчанию -- 8080) (см. Рис.~\ref{ris:debug}).

\begin{figure}[h]
\center{\includegraphics[width=0.75\linewidth]{debug}}
\caption{Отладка во встраиваемой системе}
\label{ris:debug}
\end{figure}

Процесс pdebug запускается в фоновом режиме в качестве резидентной программы (то есть такой, которая остается в памяти). В QNX его можно видеть в списке процессов, если набрать в командной строке \textit{ps} (подробности на семинарах). Аналогично и qconn. Как уже было сказано выше, qconn предоставляет доступ к файловой системе QNX удаленно из среды отладки. В отличие от pdebug+gdb взаимодействие идет не над уровнем TCP/IP пакетов в стеке OSI, а на том же уровне. То есть qnet реализует фактически свой транспортный уровень пакетов в Ethernet. Сеть qnet не имеет аутентификации и защиты и предназначена для построения высокопроизводительных распределенных систем. Отдельно о ней будет сказано далее в курсе.

% википедия
При удаленной отладке GDB запускается на одной машине, а отлаживаемая программа запускается на другой. Связь осуществляется по специальному протоколу через последовательный порт или TCP/IP. Протокол взаимодействия с отладчиком специфичен для GDB, но исходные коды необходимых подпрограмм включены в архив отладчика. Как альтернатива, на целевой платформе может быть запущена использующая тот же протокол программа pdebug из состава пакета GDB, исполняющая низкоуровневые функции вроде установки точек останова и доступа к регистрам и памяти.

Этот же режим используется для взаимодействия со встроенным отладчиком ядра Linux KGDB. С его помощью разработчик может отлаживать ядро как обычную программу: устанавливать точки останова, делать пошаговое исполнение кода, просматривать переменные. Встроенный отладчик требует наличия двух машин, соединенных через ethernet или последовательный кабель, на одном из которых запущен GDB, на другом — отлаживаемое ядро.
% википедия -- конец

\chapter{Принципы построения программно-алгоритмического обеспечения вычислительных средств АИУС}

%\section{Простейшие варианты архитектуры ПО встраиваемых систем}
%Ниже представлены простейшие варианты архитектуры встраиваемых систем, которые используются, например, в микроконтроллерах и несложных программах на DSP. Выявляются их особенности и недостатки.
%
%\subsection{Пример применения бесконечного цикла опроса в качестве основного элемента архитектуры встраиваемой системы}
%
%\subsection{Пример применения цикла, ожидающего наступления событий}
%\subsection{Пример организации работы встраиваемой системы на основе обработки прерываний}
%\subsection{Пример встраиваемой системы на основе обработки очереди сообщений}
%\subsection{Особенности построения программного обеспечения сложных информационно-управляющих систем}
%
%\section{Планирование вычислений в АИУС}
%\subsection{Ручное (жесткое) планирование вычислений в системе. Пример}
%\subsection{Варианты построения систем с ручным планированием вычислений  с использованием единого тактового генератора}
%\subsection{Многозадачные системы с использованием планировщика. Общая характеристика, особенности и проблемы}

% \section{Детали реализации многозадачности в вычислительных системах}
% \subsection{Структура задачи: локальные и глобальные переменные, процессорный квант времени, стек, приоритеты задач}
% \subsection{Переключение задач. Алгоритмы планирования: Round Robin, FIFO}

% \section{Взаимодействие вычислительных процессов. Задачи и решения}
% \subsection{Проблемы целостности данных и синхронизации. Классические задачи параллельного программирования}
% \subsection{Классические примитивы для решения задач синхронизации и совместного использования ресурсов: критические секции, барьеры, семафоры, мьютексы, мониторы}
% \subsection{Синхронизация посредством обмена сообщениями}
% \subsection{Синхронизация посредством очередей LIFO и FIFO, кольцевого буфера}

\chapter{Принципы построения программно-алгоритмического обеспечения вычислительных средств АИУС}

\addcontentsline{toc}{chapter}{Литература}
\begin{thebibliography}{99}
\bibitem{lee}Embedded Systems. Lee, Edward A. 2002. Vol. 56, London : Academic Press, 2002.
\bibitem{heath}Heath, Steve. 2003. Embedded Systems Design. s.l. : Newness, 2003. 
\bibitem{tannenbaum} Э. Танненбаум. Современные операционные системы. 3-е изд. - СПб.: Питер, 2010. — 1120 с.  
\end{thebibliography}

\end{document} % конец документа
